﻿namespace MicroCloud.Systems
{
    /// <summary>
    /// 实体类：字典数据
    /// </summary>
    [Table(nameof(KeyValue), Schema = TableSchemaConstants.System)]
    [EventEntityIgnore]
    [Description("键值数据")]
    [ValueGenerate(ValueGenerateRule.Never, ValueGenerateMode.Snowflake)]
    public class KeyValue : EntityBase<long>, IKeyValue, ILockable, ICreatedTime
    {
        #region 构造函数
        /// <summary>
        /// 初始化一个实体类：字典数据 <see cref="KeyValue"/> 的新实例
        /// </summary>
        public KeyValue()
        {
            IsLocked = false;
        }

        /// <summary>
        /// 初始化一个实体类：字典数据 <see cref="KeyValue"/> 的新实例
        /// </summary>
        /// <param name="key">数据键名</param>
        /// <param name="value">数据值</param>
        /// <param name="display">显示名称</param>
        /// <param name="remark">备注</param>、
        /// <param name="isLocked">是否锁定</param>
        public KeyValue(string key, object value, string display = "", string remark = "", bool isLocked = false)
        {
            Key = key;
            Value = value;
            Display = display;
            Remark = remark;
            IsLocked = isLocked;
        }

        #endregion

        #region 属性
        #region 获取或设置 数据键名
        private string _Key = "";
        /// <summary>
        /// 获取或设置 数据键名
        /// </summary>
        [Column("Key")]
        [Required, DefaultValue("")]
        [StringSize(StringSizeType.Name)]
        [DisplayName("数据键名")]
        public string Key { get { return _Key; } set { _Key = value.ReplaceNull(); } }
        #endregion

        #region 获取或设置 数据值JSON字符串
        private string _ValueJson = "";
        /// <summary>
        /// 获取或设置 数据值JSON字符串
        /// </summary>
        [Column("ValueJson")]
        [Required, DefaultValue("")]
        [StringMax]
        [DisplayName("数据值JSON")]
        public string ValueJson { get { return _ValueJson; } set { _ValueJson = value.ReplaceNull(); } }
        #endregion

        #region "获取或设置 数据值类型"
        private string _ValueType = "";
        /// <summary>
        /// 获取或设置 数据值类型
        /// </summary>
        [Column("ValueType")]
        [Required, DefaultValue("")]
        [StringSize(StringSizeType.General)]
        [DisplayName("数据值类型名")]
        public string ValueType { get { return _ValueType; } set { _ValueType = value.ReplaceNull(); } }
        #endregion

        #region 获取或设置 显示名称
        private string _Display = "";
        /// <summary>
        /// 获取或设置 显示名称
        /// </summary>
        [Column("Display")]
        [StringSize(StringSizeType.Name)]
        [DisplayName("显示名称")]
        public string Display { get { return _Display; } set { _Display = value.ReplaceNull(); } }
        #endregion

        #region 获取或设置 备注
        private string _Remark = "";
        /// <summary>
        /// 获取或设置 备注
        /// </summary>
        [Column("Remark")]
        [StringSize(StringSizeType.Remark)]
        [DisplayName("备注")]
        public string Remark { get { return _Remark; } set { _Remark = value.ReplaceNull(); } }
        #endregion

        #region 获取或设置 顺序编号
        /// <summary>
        /// 获取或设置 顺序编号
        /// </summary>
        [Column("OrderNo")]
        [DisplayName("顺序编号")]
        public decimal OrderNo { get; set; }
        #endregion

        #region 获取或设置 是否锁定当前信息，ILockable 可装载接口，用于IEnumerable、IQueryable筛选
        /// <summary>
        /// 获取或设置 是否锁定当前信息
        /// </summary>
        [Column("IsLocked")]
        [DisplayName("是否锁定")]
        public bool IsLocked { get; set; }
        #endregion

        #region 获取或设置 创建时间 ICreatedTime、ICreationAudited  可装载接口，在数据创建时可自动设置当前时间
        /// <summary>
        /// 获取或设置 创建时间
        /// </summary>
        [Column("CreatedTime")]
        [DisplayName("创建时间")]
        public DateTime CreatedTime { get; set; }
        #endregion

        #region 获取或设置 数据值
        /// <summary>
        /// 获取或设置 数据值
        /// </summary>
        [NotMapped]
        [DisplayName("数据值")]
        public object Value
        {
            get
            {
                if (ValueJson == null || ValueType == null)
                {
                    return null;
                }
                Type type = Type.GetType(ValueType);
                return type == null
                    ? throw new Exception(I18N.T("获取 Key 为 {0} 的字典值时类型 {1} 无法获取", Key, ValueType))
                    : ValueJson.FromJsonString(type);
            }
            set
            {
                ValueType = value?.GetType().GetFullNameWithModule();
                ValueJson = value?.ToJsonString();
            }
        }
        #endregion

        #endregion

        #region 方法
        /// <summary>
        /// 获取强类型数据值
        /// </summary>
        public T GetValue<T>()
        {
            object value = Value;
            if (Equals(value, default(T)))
            {
                return default;
            }
            if (value is T val)
            {
                return val;
            }
            try
            {
                return value.CastTo<T>();
            }
            catch (System.Exception)
            {
                throw new Exception(I18N.T("获取强类型字典值时传入类型 {0} 与实际数据类型 {1} 不匹配", typeof(T), ValueType));
            }
        }

        #endregion
    }
}